//============================================================================
// Author      : Ting Lei, leiting@gmail.com
// Version     :
// Copyright   : all rights reserved, see LICENSE file
// Description : name_table: a special, read-only bimap between continuous indices
// (e.g. long int) and   their corresponding names (e.g. string)
// origin repo: pgnetworkflow
//============================================================================

//not actually a bimap, rather a sub-class of std::vector with reverse/name lookup.

#ifndef  __nametable_h_
#define __nametable_h_

#include <vector>
#include <set>
#include <map>

#include "prettyprint.hpp"

template <typename T>
class nametable {
	std::vector<T> names_;
	std::set<T> name_values_;
	std::map<T, typename std::vector<T>::size_type> name_index_;
public:
	bool from_vec(const std::vector<T>& names) {
		clear();
		for (size_t i = 0; i < names.size(); i++) {
			auto n = names[i];
			if (name_values_.find(n) == name_values_.end()){
				names_.emplace_back(n);
				name_values_.emplace(n);
				name_index_[n] = i;
			} else {
				return false;
			}
		}
		return true;
	}

	const std::vector<T>& as_vec() const {
		return names_;
	}

	void clear() noexcept {
		names_.clear();
		name_values_.clear();
		name_index_.clear();
	}

	bool contains(const T& t) const {
		return name_values_.find(t) != name_values_.end();
	}

	const T& operator[](int i) const { return names_.at(i); } // range-checked
	size_t index(const T& n) const { return name_index_.at(n); }
	size_t operator()(const T& n) const { return index(n); }
	size_t size(void) const { return names_.size(); }

	template<class T1>
	friend std::ostream& operator<<(std::ostream& __s, const nametable<T1>& nt);

};

template<typename T>
std::ostream& operator<<(std::ostream& __s, const nametable<T>& nt) {
	__s << nt.names_;
	return __s;
}


#endif //__nametable_h_
